package com.lei.android.videoline.VideoLineView;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Build;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.ColorInt;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

import com.lei.android.videoline.R;

import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

/**
 * Author LEI
 * Date 2020/1/1 13:12
 * Description  视频时间轴
 */
public class VideoLineBar extends View {

    private final String TAG = VideoLineBar.class.getSimpleName();

    private static final int ONE_HOUR_MILLISECOND = 60 * 60 * 1000; // 1小时的毫秒值
    private static final int ONE_HOUR_SECONDS = 60 * 60; // 1小时的秒值
    private static final int ONE_HOUR_MINUTE = 60; // 1小时的分钟值

    public static final int ONE_HOUR_SCALE_COUNT = 2; // 1小时之间的大刻度个数
    private static final int ONE_MAX_SCALE_VALUE = ONE_HOUR_MILLISECOND / ONE_HOUR_SCALE_COUNT; // 每个大刻度代表的毫秒值(30分钟)
    public static final int SCALE_COUNT = 30; // 每个大刻度之间小刻度的个数（包括中刻度）
    public static final int SCALE_VALUE_MILLISECOND = ONE_MAX_SCALE_VALUE / SCALE_COUNT; // 1个刻度代表的值（单位：毫秒）
    private static final int SCALE_VALUE_SECONDS = SCALE_VALUE_MILLISECOND / 1000; // 1个刻度代表的值（单位：秒）
    private static final int SCALE_VALUE_MINUTE = SCALE_VALUE_SECONDS / 60; // 1个刻度代表的值（单位：分）

    private static final int DEFAULT_SCALE_WIDTH = CUtils.dp2px(25);

    /**
     * 中轴线画笔
     */
    private Paint centerLinePaint = new Paint();
    private Bitmap centerLineBitmap;
    /**
     * 刻度配置
     */
    private int scaleColor = 0xffb5b5b5;//刻度的颜色
    /**
     * 大刻度
     */
    private Paint bigScalePaint = new Paint();//大刻度画笔
    private int scaleWidthBig = CUtils.dp2px(0.5f);//大刻度的宽度
    private int scaleHeightBig = CUtils.dp2px(30);//大刻度的高度
    /**
     * 中刻度
     */
    private Paint middleScalePaint = new Paint();
    private int scaleWidthMiddle = CUtils.dp2px(0.5f);//大刻度的宽度
    private int scaleHeightMiddle = CUtils.dp2px(20);//大刻度的高度
    /**
     * 小刻度
     */
    private Paint smallScalePaint = new Paint();
    private int scaleWidthSamll = CUtils.dp2px(0.5f);//小刻度的宽度
    private int scaleHeightSamll = CUtils.dp2px(10);//小刻度的高度
    /**
     * 上下两条线
     */
    private Paint upAndDownLinePaint = new Paint();//刻度画笔
    private int upAndDownLineWidth = CUtils.dp2px(1);//上下两条线的宽度
    private int upAndDownLineColor = scaleColor;
    /**
     * 时间文字
     */
    private TextPaint scaleTextPaint = new TextPaint();
    private int scaleTextColor = 0xff444242;//文本颜色
    private int scaleTextSize = CUtils.sp2px(10);//文本大小
    /**
     * 视频区域
     */
    private Paint vedioAreaPaint = new Paint();
    private int vedioAreaBg = 0x336e9fff;//视频背景颜色
    private RectF vedioAreaRect = new RectF();

    private int mHeight;
    private int mWidth;
    /**
     * 当前时间的毫秒值
     */
    private long currentTimeMillis;
    /**
     * 记录缩放前的时间
     */
    private long lastTimeMillis;
    /**
     * 刻度缩放值
     */
    private float zoom = 0f;
    private float mScaleWidth = DEFAULT_SCALE_WIDTH + zoom;
    /**
     * 滑动结果回调
     */
    private OnBarMoveListener onBarMoveListener;
    private List<VideoInfo> videoInfoList;
    /**
     * 是否允许更新实时位置
     */
    private boolean isUpdateRealtimePosition = true;


    public VideoLineBar(Context context) {
        super(context);
    }

    public VideoLineBar(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public VideoLineBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public VideoLineBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context);
    }

    private void init(Context context) {
        centerLinePaint.setAntiAlias(true);

        bigScalePaint.setAntiAlias(true);
        bigScalePaint.setColor(scaleColor);
        bigScalePaint.setStrokeWidth(scaleWidthBig);

        middleScalePaint.setAntiAlias(true);
        middleScalePaint.setColor(scaleColor);
        middleScalePaint.setStrokeWidth(scaleWidthMiddle);

        smallScalePaint.setAntiAlias(true);
        smallScalePaint.setColor(scaleColor);
        smallScalePaint.setStrokeWidth(scaleWidthSamll);

        scaleTextPaint.setAntiAlias(true);
        scaleTextPaint.setColor(scaleTextColor);
        scaleTextPaint.setTextSize(scaleTextSize);

        vedioAreaPaint.setAntiAlias(true);
        vedioAreaPaint.setColor(vedioAreaBg);

        upAndDownLinePaint.setAntiAlias(true);
        upAndDownLinePaint.setColor(upAndDownLineColor);
        upAndDownLinePaint.setStrokeWidth(upAndDownLineWidth);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        centerLineBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.video_ruler_current_location_ic);
        mHeight = centerLineBitmap.getHeight();
        mWidth = (int) measureVideoLine(widthMeasureSpec);
        setMeasuredDimension(mWidth, mHeight);
    }

    private float measureVideoLine(int measureSpec) {
        float result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        switch (specMode) {
            case MeasureSpec.AT_MOST:
                result = mScaleWidth;
                break;
            case MeasureSpec.EXACTLY:
                result = Math.max(specSize, mScaleWidth);
                break;
        }
        return result;
    }


    private float mStartX = 0;
    private boolean isDoubleTouch;
    private float beforeLength, afterLenght, mScale;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            Log.e(TAG, "setOnTouchListener----ACTION_DOWN");
            mStartX = event.getX();
            //单指按下
            isDoubleTouch = false;
//            isUpdateRealtimePosition = false;
        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
            Log.e(TAG, "setOnTouchListener----ACTION_MOVE");
            if (event.getPointerCount() == 2 && isDoubleTouch) {
                //双指移动
                afterLenght = getDistance(event);// 获取两点的距离
                if (beforeLength == 0) {
                    beforeLength = afterLenght;
                }
                float gapLenght = afterLenght - beforeLength;// 变化的长度
                if (Math.abs(gapLenght) > 5f) {
                    mScale = afterLenght / beforeLength;// 求的缩放的比例
                    //双指缩放了
                    beforeLength = afterLenght;
                    onZooming();
                }
            } else {
                //单指移动
                float distance = event.getX() - mStartX;
                long zeng = getTimeByDistance(distance);
                mStartX = event.getX();
                currentTimeMillis = currentTimeMillis - zeng;
                invalidate();
                if (onBarMoveListener != null) {
                    onBarMoveListener.onDragBar(currentTimeMillis, getVideoInfoBySelectedTime(currentTimeMillis));
                }
            }
        } else if (event.getAction() == MotionEvent.ACTION_UP) {
            Log.e(TAG, "setOnTouchListener----ACTION_UP");
//            isUpdateRealtimePosition = true;
            if (isDoubleTouch) {
                //双指抬起
                new Timer().schedule(new TimerTask() {
                    @Override
                    public void run() {
                        post(new Runnable() {
                            @Override
                            public void run() {
//                                setIsCanScrollBar(true);//双指抬起的时候，需要解除静止滑动
                            }
                        });
                    }
                }, 100);

            } else {

            }
        } else if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_DOWN) {
            Log.e(TAG, "setOnTouchListener----ACTION_POINTER_DOWN");
            if (event.getPointerCount() == 2) {
                Log.e(TAG, "setOnTouchListener----ACTION_POINTER_DOWN222222");
                //双指按下
                lastTimeMillis = currentTimeMillis;
                beforeLength = getDistance(event);
                isDoubleTouch = true;
//                isUpdateRealtimePosition = false;
                return true;
            }
        }
        return true;
    }

    /**
     * 缩放中
     */
    private void onZooming() {
        if (mScale > 1) {
            zoom += 5;
        } else {
            zoom -= 5;
        }
        // 允许缩放范围
        if (zoom > -DEFAULT_SCALE_WIDTH * 0.8f && zoom < DEFAULT_SCALE_WIDTH * 1.2f) {
            currentTimeMillis = lastTimeMillis;
            mScaleWidth = DEFAULT_SCALE_WIDTH + zoom;
            invalidate();
        }

//        if (onBarMoveListener != null) {
//            onBarMoveListener.onBarMoving(currentTimeMillis);
//        }
    }

    /**
     * 计算两点的距离(避免计算误差，int)
     **/
    private float getDistance(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return (float) Math.sqrt(x * x + y * y);
    }

    /**
     * 根据时间获取该时间在当前数轴的X坐标
     *
     * @param timeMillis
     * @return
     */
    private float getXByTime(long timeMillis) {
        float millisecondWidth = mScaleWidth /  SCALE_VALUE_MILLISECOND;
        long s = timeMillis - currentTimeMillis;
        float x = mWidth / 2.0f + s * millisecondWidth;
        return x;
    }

    private int getTimeByDistance(float distance) {
        float millisecondWidth = mScaleWidth / SCALE_VALUE_MILLISECOND;
        return Math.round((distance / millisecondWidth));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawVedioArea(canvas);
        drawLine(canvas);
        drawScale(canvas, currentTimeMillis, mWidth / 2, true);
        drawScale(canvas, currentTimeMillis, mWidth / 2, false);
    }

    /**
     * 画中间线和上下两条线
     *
     * @param canvas
     */
    private void drawLine(Canvas canvas) {
        canvas.drawBitmap(centerLineBitmap, getWidth() / 2 - centerLineBitmap.getWidth() / 2, 0, centerLinePaint);
        canvas.drawLine(0, upAndDownLineWidth / 2, mWidth, upAndDownLineWidth / 2, upAndDownLinePaint);
        canvas.drawLine(0, mHeight - upAndDownLineWidth / 2, mWidth, mHeight - upAndDownLineWidth / 2, upAndDownLinePaint);
    }

    /**
     * 绘制刻度
     *
     * @param canvas
     * @param timeMillis
     * @param isDrawLeft
     */
    private void drawScale(Canvas canvas, long timeMillis, float startX, boolean isDrawLeft) {
        long nextTime = 0;
        long residue = timeMillis % SCALE_VALUE_MILLISECOND;

        if (residue == 0) {
            nextTime = isDrawLeft ? timeMillis - SCALE_VALUE_MILLISECOND : timeMillis + SCALE_VALUE_MILLISECOND;
            startX = isDrawLeft ? startX - mScaleWidth : startX + mScaleWidth;
        } else {
            nextTime = isDrawLeft ? timeMillis - residue : timeMillis - residue + SCALE_VALUE_MILLISECOND;
            //重新计算startX;
            float v = mScaleWidth / SCALE_VALUE_MILLISECOND;//计算出每一毫秒秒的距离
            startX = isDrawLeft ? startX - residue * v : startX + (SCALE_VALUE_MILLISECOND - residue) * v;
        }
//        Log.e(TAG, "startX = " + startX + "  mWidth = " + mWidth);
        if (startX < 0 || startX > mWidth) {
            return;
        }

        if (nextTime % ONE_MAX_SCALE_VALUE == 0) { //大刻度

            //画中间的大刻度
            float startY = upAndDownLineWidth / 2 + (mHeight - scaleHeightBig) / 2;
            float stopY = mHeight - startY;
            scaleTextPaint.setColor(scaleColor);
            canvas.drawLine(startX, startY, startX, stopY, bigScalePaint);
            // 画文字
//            float timeStrWidth = scaleTextPaint.measureText(VideoLineDateUtils.getHourMinuteByIndex(curScaleIndex));
            scaleTextPaint.setColor(scaleTextColor);
            scaleTextPaint.setTextSize(scaleTextSize);

            String time = VideoLineDateUtils.long2StringTime(nextTime, "HH:mm");
            canvas.drawText(time, startX + scaleHeightSamll * 0.5f, mHeight - scaleHeightSamll * 0.7f, scaleTextPaint);
            if ("00:00".equals(time) || "23:30".equals(time)) {
                canvas.drawText(VideoLineDateUtils.long2StringTime(nextTime, "yyyy-MM-dd"), startX + scaleHeightSamll * 0.5f, scaleHeightSamll * 1.3f, scaleTextPaint);
            }

        } else if (nextTime % (ONE_MAX_SCALE_VALUE / 6) == 0) { // 中刻度

            //画中间的中刻度
            float startY = upAndDownLineWidth / 2 + (mHeight - scaleHeightMiddle) / 2;
            float stopY = mHeight - startY;
            scaleTextPaint.setColor(scaleColor);
            canvas.drawLine(startX, startY, startX, stopY, middleScalePaint);

            scaleTextPaint.setColor(scaleTextColor);
            scaleTextPaint.setTextSize(scaleTextSize);
            String time = VideoLineDateUtils.long2StringTime(nextTime, "HH:mm");
            if (zoom > DEFAULT_SCALE_WIDTH * 0.01f) {
                canvas.drawText(time, startX + scaleHeightSamll * 0.5f, mHeight - scaleHeightSamll * 0.7f, scaleTextPaint);
            }

        } else {//小刻度

            //画中间的小刻度
            float startY = upAndDownLineWidth / 2 + (mHeight - scaleHeightSamll) / 2;
            float stopY = mHeight - startY;
            scaleTextPaint.setColor(scaleTextColor);
            canvas.drawLine(startX, startY, startX, stopY, smallScalePaint);

        }
        drawScale(canvas, nextTime, startX, isDrawLeft);
    }

    /**
     * 绘制视频区域
     *
     * @param canvas
     */
    private void drawVedioArea(Canvas canvas) {
        for (VideoInfo videoInfo : videoInfoList) {
            long start = videoInfo.getStartTimeMillis();
            long end = videoInfo.getEndTimeMillis();
            if (end <= start) continue;
            float s = getXByTime(videoInfo.getStartTimeMillis());
            float e = getXByTime(videoInfo.getEndTimeMillis());
//            if (e > 0 || e > mWidth) {
//                vedioAreaRect.set(s < 0 ? 0 : s, mHeight / 2 - 30, e > mWidth ? mWidth : e, mHeight / 2 - 10);
                vedioAreaRect.set(s < 0 ? 0 : s, 0, e > mWidth ? mWidth : e, mHeight);
            vedioAreaPaint.setColor(videoInfo.getEventColor());
                canvas.drawRect(vedioAreaRect, vedioAreaPaint);
//            }
        }
    }

    /**
     * 根据时间获取所处的视频区间
     *
     * @param selectedTime
     * @return
     */
    private VideoInfo getVideoInfoBySelectedTime(long selectedTime) {
        for (int i = 0; i < videoInfoList.size(); i++) {
            //判断是否在一个视频回放时间区间内
            if (VideoLineDateUtils.isInnerVideoArea(videoInfoList.get(i), selectedTime)) {
                return videoInfoList.get(i);
            }
        }
        return null;
    }

    /**
     * 设置当前时间
     *
     * @param currentTimeMillis
     */
    public void setCurrentTimeMillis(long currentTimeMillis) {
        this.currentTimeMillis = currentTimeMillis;
        this.lastTimeMillis = currentTimeMillis;
        invalidate();
    }

    public void setVideoInfoList(List<VideoInfo> videoInfoList) {
        this.videoInfoList = videoInfoList;
        invalidate();
    }

    /**
     * 定位到指定位置
     *
     * @param targetTimeMillis 目标时间
     */
    public synchronized void locationToTargetTime(long targetTimeMillis, boolean isCallback) {
        setCurrentTimeMillis(targetTimeMillis);
        if (onBarMoveListener != null && isCallback) {
            onBarMoveListener.onDragBarFinish(targetTimeMillis, getVideoInfoBySelectedTime(targetTimeMillis));
        }
    }

    /**
     * 设置刻度时间颜色
     *
     * @param scaleTextColor
     */
    public void setScaleTextColor(@ColorInt int scaleTextColor) {
        this.scaleTextColor = scaleTextColor;
        invalidate();
    }

    /**
     * 设置刻度颜色
     *
     * @param scaleColor
     */
    public void setScaleColor(@ColorInt int scaleColor) {
        this.scaleColor = scaleColor;
        invalidate();
    }

    public boolean isUpdateRealtimePosition() {
        return isUpdateRealtimePosition;
    }

    /**
     * 拿到当前时间
     *
     * @return
     */
    public long getCurrentTimeMillis() {
        return currentTimeMillis;
    }

    /**
     * 设置移动监听
     *
     * @param onBarMoveListener
     */
    public void setOnBarMoveListener(OnBarMoveListener onBarMoveListener) {
        this.onBarMoveListener = onBarMoveListener;
    }

}
